package com.framework.spring.aop.aspect;

import com.framework.spring.aop.service.DeleteService;
import com.framework.spring.aop.service.impl.DeleteBServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @Title: 申明Aspect，并且交给spirng容器管理
 * @Description: 功能概述:
 * @Author: lihaiyang
 * @version: 1.0 .
 * @Date: 2024-01-03 11:48
 * @Copyright: Copyright(c)2024
 */
@Component
@Aspect
@Slf4j(topic = "e")
public class NotVeryUsefulAspect {

	/**
	 * 声明切入点，匹配User到所有的方法调用
	 * execution 匹配方法执行连接点
	 * within：将撇撇限制为特定的连接点
	 * args：参数
	 * target：目标对象
	 * this：代理对象
	 */
	@Pointcut("execution(* com.framework.spring.aop.service..*.*(..))")
	private void pointCut() {

	}

	/**
	 * within 颗粒度粗
	 * 需要指定到指定包 com.framework.spring.aop.service.impl.* 后面必须有*或者指定类
	 * 需要指定到指定包和子包 com.framework.spring.aop.service..* 后面必须有*或者指定类
	 */
	@Pointcut("within(com.framework.spring.aop.service..AServiceImpl)")
	private void pointCut2() {

	}

	/**
	 * within 颗粒度粗
	 * 需要指定到指定包 com.framework.spring.aop.service.impl.* 后面必须有*或者指定类
	 * 需要指定到指定包和子包 com.framework.spring.aop.service..* 后面必须有*或者指定类
	 */
	@Pointcut("within(com.framework.spring.aop.service..*)")
	private void pointCut3() {

	}

	/**
	 * args 匹配的是方法在声明时指定的方法参数类型
	 */
	@Pointcut("args(java.lang.Integer, java.lang.String)")
	private void pointCut4() {

	}

	/**
	 * target 代理对象是指定类型的 需要有自己的实现
	 */
	@Pointcut("target(com.framework.spring.aop.service.AService)")
	private void pointCut5() {

	}

	/**
	 * this 代理对象就是自己
	 */
	@Pointcut("this(com.framework.spring.aop.service.impl.A1ServiceImpl)")
	private void pointCut6() {

	}

	@DeclareParents(value = "com.framework.spring.aop.service.impl.UserServiceImpl", defaultImpl = DeleteBServiceImpl.class)
	public static DeleteService deleteService;

	@Pointcut("@args(com.framework.spring.aop.anno.Aop)")
	private void pointCut7() {

	}

	@Pointcut("execution(* com.framework.spring.aop.service..*.*(..))")
	private void pointCut8() {

	}

	/**
	 * 声明before通知，在pointcut切入点前执行
	 * 通知与切入点表达式相关联
	 * 并且切入点匹配的方法执行之前，之后或者前后运行
	 * 切入点表达式可以是指定切入点的简单引用，也可以是在适当的位置声明切入点表达式
	 */
	@Before("pointCut()")
	public void adviceBefore() {
		log.info("before aop");
	}

	@After("pointCut()")
	public void adviceAfter() {
		log.info("after aop");
	}

	@AfterReturning("pointCut()")
	public void adviceAfterReturning() {
		log.info("AfterReturning aop");
	}

	@AfterThrowing("pointCut()")
	public void adviceAfterThrowing() {
		log.info("AfterThrowing aop");
	}

	@Around("pointCut()")
	public Object adviceAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
		log.info("Around aop start");
		// 在目标方法前后执行的通知逻辑

		// 可以在此处编写需要在目标方法前后执行的代码或操作

		Object result;
		try {
			// 调用proceed()方法执行目标方法
			result = proceedingJoinPoint.proceed();

			// 目标方法执行后的操作
			// 可以获取目标方法的返回值：result

		} catch (Exception ex) {
			// 异常处理操作
			throw ex;
		}

		log.info("Around aop end");
		return result;
	}
}
